﻿==============================================================================
DOSYA ADI  : User.h
KAYNAK      : -GameServer\User.h
SISTEM      : v2369 Reconnect - SUNUCU
BOYUT       : 119137 bayt / 3558 satir
ACIKLAMA    : CUser uye/method bildirimleri, GAME_STATE_SUSPENDED, isSuspended()
ESLESME     : 60 satir / 5 blok
==============================================================================

NOT: Bu dosya yalnizca RECONNECT ile ilgili kod bloklarini icerir.
     Satir numaralari KAYNAK dosyadaki orijinal satirlardir.

----------------------------------------------------------------------
>> KAYNAK SATIR 1 - 33
----------------------------------------------------------------------
     1 | #pragma once
     2 | 
     3 | #include "LuaEngine.h"
     4 | #include "../shared/KOSocket.h"
     5 | #include "MagicInstance.h"
     6 | #include "Unit.h"
     7 | #include "ChatHandler.h"
     8 | #include "ReconnectSuspend.h"
     9 | 
    10 | struct _KNIGHTS_USER;
    11 | struct _EXCHANGE_ITEM;
    12 | struct _USER_SEAL_ITEM;
    13 | 
    14 | typedef std::map<uint64, _USER_SEAL_ITEM*>	UserItemSealMap;
    15 | typedef	std::list<_EXCHANGE_ITEM*>			ItemList;
    16 | typedef CSTLMap <_USER_QUEST_INFO, uint16>	QuestMap;
    17 | typedef CSTLMap <_DAILY_USERQUEST, uint8>	DailyQuestMap;
    18 | typedef	std::map<uint32, _cooldown>			SkillCooldownList;
    19 | typedef	std::map<uint32, _castlist>			SkillCastList;
    20 | typedef	std::map<uint32, time_t>			PetSkillCooldownList;
    21 | typedef	std::map<uint8, _type_cooldown>			MagicTypeCooldownList;
    22 | typedef	std::map<uint32, ULONGLONG>			UserSavedMagicMap;
    23 | 
    24 | typedef std::map<uint8, int16> ItemBonusMap;
    25 | typedef std::map<uint8, ItemBonusMap> EquippedItemBonuses;
    26 | 
    27 | typedef std::vector<_ZONE_ONLINE_REWARD> ZoneOnlineReward;
    28 | 
    29 | // Time (in seconds) between each save request (10 min).
    30 | #define PLAYER_SAVE_INTERVAL			(10 * 60)
    31 | // Time (in milliseconds) between each skill request (-1 sec).
    32 | #define PLAYER_SKILL_REQUEST_INTERVAL	800 // milliseconds (ms)
    33 | // Time (in milliseconds) between each r hit request (-1 sec).

----------------------------------------------------------------------
>> KAYNAK SATIR 38 - 88
----------------------------------------------------------------------
    38 | #define DAILY_OPERATIONS_MINUTE			1440
    39 | // Time (in seconds) for nation monuments
    40 | #define NATION_MONUMENT_REWARD_SECOND	60
    41 | 
    42 | #define PLAYER_OFF_MERCHANT_INTERVAL (1*MINUTE)
    43 | 
    44 | // Time (in seconds) for stamina change
    45 | #define PLAYER_STAMINA_INTERVAL 2
    46 | // Time (in seconds) for training exp change
    47 | #define PLAYER_TRAINING_INTERVAL 15
    48 | // time genie updated
    49 | #define PLAYER_GENIE_INTERVAL	(1 * MINUTE)
    50 | #define PLAYER_FLASH_INTERVAL	(1 * MINUTE)
    51 | //time monster stone updated
    52 | #define PLAYER_MONSTER_STONE_INTERVAL	(30 * MINUTE)
    53 | #define PLAYER_MONSTER_STONE_KILL_INTERVAL	20
    54 | 
    55 | // Time for Check PPCard Serial Time
    56 | #define PPCARD_TIME (40)
    57 | 
    58 | enum class GameState
    59 | {
    60 | 	NONE,
    61 | 	GAME_STATE_CONNECTED,
    62 | 	GAME_STATE_INGAME,
    63 | 	// Reconnect sistemi: karakter oyunda kalır ancak işlevsizdir.
    64 | 	// Yalnızca UI panelinden gelen onay paketi işlenir.
    65 | 	GAME_STATE_SUSPENDED
    66 | };
    67 | 
    68 | enum MerchantState
    69 | {
    70 | 	MERCHANT_STATE_NONE = -1,
    71 | 	MERCHANT_STATE_SELLING = 0,
    72 | 	MERCHANT_STATE_BUYING = 1
    73 | };
    74 | 
    75 | enum BotState
    76 | {
    77 | 	BOT_AFK = 0,
    78 | 	BOT_MINING = 1,
    79 | 	BOT_FISHING = 2,
    80 | 	BOT_FARMER = 3,
    81 | 	BOT_FARMERS = 4,
    82 | 	BOT_MERCHANT = 5,
    83 | 	BOT_DEAD = 6,
    84 | 	BOT_MOVE = 7,
    85 | 	BOT_MERCHANT_MOVE = 8,
    86 | 	BOT_NPC_MOVE = 9
    87 | };
    88 | 

----------------------------------------------------------------------
>> KAYNAK SATIR 256 - 338
----------------------------------------------------------------------
   256 | 	ULONGLONG  m_TownTime;
   257 | 
   258 | 	bool m_dailyrankrefresh[(int)DailyRankType::COUNT];
   259 | 
   260 | 	uint16  m_offmerchanttime;
   261 | 
   262 | 	uint8	m_bAccountStatus;
   263 | 	uint8	m_bPremiumType[5];
   264 | 	uint16	m_sPremiumTime[5];
   265 | 
   266 | 	bool	m_bWaitingOrder;
   267 | 	time_t	m_tOrderRemain;
   268 | 
   269 | 	bool	m_autoloot;
   270 | 	bool	m_fairycheck;
   271 | 
   272 | 	time_t	m_event_afkcheck;
   273 | 	uint8 TimeTravelTemp;
   274 | 	uint32  m_nKnightCash;
   275 | 	uint32  m_nTLBalance;
   276 | 	uint8 priesterrorcount;
   277 | 	time_t	m_1098GenieTime;
   278 | 	uint8   m_sFirstUsingGenie;
   279 | 	char	m_GenieOptions[100];
   280 | 	bool	m_bGenieStatus;
   281 | 	uint32	m_reconnectToken;
   282 | 	ULONGLONG m_reconnectPendingDisconnectAt;
   283 | 	bool	m_reconnectHydrating;
   284 | 	bool	m_reconnectRestoreGenie;
   285 | 	int8	m_reconnectMerchantState;
   286 | 	uint8	m_reconnectRestoreZone;
   287 | 	float	m_reconnectRestoreX;
   288 | 	float	m_reconnectRestoreY;
   289 | 	float	m_reconnectRestoreZ;
   290 | 	bool	m_reconnectRestoreMerchant;
   291 | 	bool	m_reconnectRestorePremiumMerchant;
   292 | 	_MERCH_DATA	m_reconnectMerchantItems[MAX_MERCH_ITEMS];
   293 | 	// Reconnect parti persistence: disconnect anında ticket'a yazılan parti
   294 | 	// durumu; karakter yüklemesi sonrası RestoreReconnectParty() ile geri
   295 | 	// yüklenir (üyelik disconnect'te silinmez).
   296 | 	bool	m_reconnectRestorePartyValid;
   297 | 	int16	m_reconnectRestorePartyID;
   298 | 	int8	m_reconnectRestorePartySlot;
   299 | 	uint16	m_reconnectRestorePartySocket;
   300 | 	bool	m_reconnectRestorePartyLeader;
   301 | 	bool	m_reconnectRestorePartyCommandLeader;
   302 | 	uint8	m_reconnectRestorePartyType;
   303 | 	// Reconnect HOLD: panelin açıldığı andaki sabit konum. "Yes" onayında
   304 | 	// karakter tam bu koordinata ışınlanır (WIZ_WARP / CUser::Warp).
   305 | 	// Askı boyunca sunucu konumu donuk kalır; istemcinin yerel yürüyüşü
   306 | 	// bu sayede "Yes" basıldığında iptal edilir.
   307 | 	bool	m_reconnectAnchorValid;
   308 | 	uint8	m_reconnectAnchorZone;
   309 | 	float	m_reconnectAnchorX;
   310 | 	float	m_reconnectAnchorY;
   311 | 	float	m_reconnectAnchorZ;
   312 | 	// Reconnect sistemi (SUSPENDED) durum çekirdeği.
   313 | 	CReconnectSuspend m_reconnectSuspend;
   314 | 
   315 | 	bool	m_iswanted;
   316 | 	uint32  m_iswantedtime;
   317 | 
   318 | 	int16   m_TowerOwnerID;
   319 | 
   320 | 	int16	m_oldTargetID;
   321 | 	// Mute-Attack Related
   322 | 	int32 m_mutetimestatus, m_attacktimestatus;
   323 | 
   324 | 	uint32 m_flashtime;
   325 | 	uint8  m_flashcount, m_flashtype;
   326 | 
   327 | 	//Civciv 30 level 1 kere kontrol
   328 | 	uint8 ChickenStatus;
   329 | 
   330 | 	// Achieve System
   331 | 	_USER_ACHIEVE_SUMMARY m_AchieveInfo;
   332 | 	uint16 m_sCoverID, m_sCoverTitle, m_sSkillID, m_sSkillTitle;
   333 | 	AchieveMap m_AchieveMap;
   334 | 	AchieveTimedMap m_AchieveTimedMap;
   335 | 
   336 | 	time_t	m_lastStaminaTime;
   337 | 	time_t	m_lastTrainingTime;
   338 | 	uint32  m_iTotalTrainingExp;

----------------------------------------------------------------------
>> KAYNAK SATIR 779 - 868
----------------------------------------------------------------------
   779 | 			return GetLifeSkillProgress(m_lifeSkills.SmitheryExp);
   780 | 			break;
   781 | 		case LIFE_SKILL::KARMA:
   782 | 			return GetLifeSkillProgress(m_lifeSkills.KarmaExp);
   783 | 			break;
   784 | 		default:
   785 | 			return LF_VEC2(0, 100);
   786 | 			break;
   787 | 		}
   788 | 	}
   789 | 	// globals
   790 | 	uint32 m_mackey;
   791 | 	void XSafe_Main();
   792 | 	void WareHouseAddItemProcess(uint32 ItemID, uint32 Count);
   793 | 	uint8_t CheckEmptyWareHouseSlot();
   794 | 
   795 | 	void WantedEventUserisMove();
   796 | 	void WantedProcess(Packet& pkt);
   797 | 	void WantedRegister(Packet& pkt);
   798 | 	void NewWantedEventLoqOut(Unit* pKiller = nullptr);
   799 | 	void CyberACS_BotPriestSystem();
   800 | 	float getplusdamage();
   801 | 	int16	m_bUserPriestBotID;
   802 | 	// handlers
   803 | 	void XSafe_HandlePacket(Packet& pkt);
   804 | 	void SendReconnectToken();
   805 | 	void SendReconnectUiTrigger();
   806 | 	void SendReconnectDisconnectNotice();
   807 | 	// Reconnect hakkını iptal eder: token/ticket silinir ve istemciye
   808 | 	// RECONNECT_REQ_REVOKE bildirimi gönderilir (AC token'ı temizler).
   809 | 	void SendReconnectRevoke();
   810 | 	// Premium durumu değişiminde reconnect hakkını senkronlar: premium
   811 | 	// aktifleştiyse token dağıtır, düştüyse hakkı iptal eder (askıdaysa
   812 | 	// askıyı kapatıp doğrudan disconnect uygular).
   813 | 	void SyncReconnectEligibility();
   814 | 	void HandleReconnectResume(Packet& pkt);
   815 | 	void ArmReconnectTicket();
   816 | 	void ArmReconnectPendingDisconnect(uint32 holdSeconds);
   817 | 	void CancelReconnectPendingDisconnect();
   818 | 	bool ProcessReconnectPendingDisconnect();
   819 | 	void RestoreReconnectMerchant();
   820 | 	// Disconnect/reconnect sırasında korunan parti üyeliğini yeni oturuma bağlar.
   821 | 	void RestoreReconnectParty();
   822 | 	// Reconnect akışı sürüyor mu? (askı aktif ya da disconnect edilmiş ticket)
   823 | 	// Bu pencerede parti üyeliği gibi oturum durumları korunur.
   824 | 	bool IsReconnectPending();
   825 | 
   826 | 	// Reconnect hakkı yalnızca premium oyunculara tanınır. Premiumu olmayan
   827 | 	// oyuncuya token dağıtılmaz, askı paneli açılmaz ve kopmada resume
   828 | 	// ticket'ı oluşmaz; oyuncu doğrudan normal disconnect akışına düşer.
   829 | 	bool IsReconnectEligible() const;
   830 | 
   831 | 	// --- Reconnect / SUSPENDED durum yönetimi -----------------------------
   832 | 	// Askı anındaki kimlik anlık görüntüsünü (hesap/karakter/ID/oturum) üretir.
   833 | 	ReconnectIdentity BuildReconnectIdentity();
   834 | 	// Karakteri SUSPENDED durumuna alır ve istemciye UI paneli paketini gönderir.
   835 | 	bool SuspendForReconnect(uint8 holdSeconds, const char* reason = "reconnecttest");
   836 | 	// UI panelinden gelen onay paketini işler (güvenlik doğrulaması + IN_GAME).
   837 | 	bool HandleReconnectConfirm(Packet& pkt, uint8 requestType);
   838 | 	// Süre kontrolü; süre dolduysa true döner ve askıyı kapatır.
   839 | 	bool UpdateReconnectSuspend();
   840 | 	// Askıyı kapatır ve durumu tekrar IN_GAME yapar (kurtarma/iptal yolu).
   841 | 	void ReleaseReconnectSuspend(const char* reason);
   842 | 	// SUSPENDED iken paketin işlenmesine izin var mı? (paket filtresi)
   843 | 	bool IsReconnectPacketAllowed(uint8 opcode, Packet& pkt);
   844 | 	void XSafe_General(Packet& pkt);
   845 | 	void XSafe_StayAlive(Packet& pkt);
   846 | 	void XSafe_Reset(Packet& pkt);
   847 | 	void XSafe_AuthInfo(Packet& pkt);
   848 | 	void XSafe_ProcInfo(Packet& pkt);
   849 | 	void XSafe_Log(Packet& pkt);
   850 | 	void XSafe_UIRequest(Packet& pkt);
   851 | 	void XSafe_PusRequest(Packet& pkt);
   852 | 	void XSafe_PUSPurchase(Packet& pkt);
   853 | 	void PUSGiftPurchase(Packet& pkt);
   854 | 	void XSafe_DropRequest(Packet& pkt);
   855 | 	void XSafe_ReqUserInfo(Packet& pkt);
   856 | 	void XSafe_SaveLootSettings(Packet& pkt);
   857 | 	void XSafe_ChaoticExchange(Packet& pkt);
   858 | 	void SendChaoticResult(uint8 result);
   859 | 	void XSafe_Merchant(Packet& pkt);
   860 | 	void XSafe_ReqUserData();
   861 | 	void XSafe_SendTempItems();
   862 | 	void XSafe_Support(Packet& pkt);
   863 | 	void XSafe_ItemNotice(uint8 type, uint32 nItemID);
   864 | 	void XSafe_ReqMerchantList(Packet& pkt);
   865 | 	void XSafe_SendMessageBox(std::string title, std::string message);
   866 | 	void XSafe_SendLifeSkills();
   867 | 	void XSafe_HandleLifeSkill(Packet& pkt);
   868 | 	void XSafe_LotteryJoinFunction(Packet& pkt);

----------------------------------------------------------------------
>> KAYNAK SATIR 963 - 1015
----------------------------------------------------------------------
   963 | 
   964 | 	INLINE uint16 GetGenieTime() {
   965 | 		int hour = int(m_1098GenieTime > UNIXTIME ? m_1098GenieTime - UNIXTIME : 0);
   966 | 		if (hour <= 0)   return 0;
   967 | 		if (hour < 3600) return 1;
   968 | 
   969 | 		double test = hour / static_cast<double>(3600);
   970 | 		return (uint16)round(test);
   971 | 	}
   972 | 	INLINE uint16 GetAchieveLoginTime() { return m_bAchieveLoginTime; }
   973 | 
   974 | 	INLINE bool isMuted() { return m_mutetimestatus > (int32)UNIXTIME || m_mutetimestatus == -1; }
   975 | 	INLINE bool isAttackDisabled() { return m_attacktimestatus > (int32)UNIXTIME || m_attacktimestatus == -1; }
   976 | 	INLINE bool isGM() { return GetAuthority() == (uint8)AuthorityTypes::AUTHORITY_GAME_MASTER; }
   977 | 	INLINE bool isGMUser() { return GetAuthority() == (uint8)AuthorityTypes::AUTHORITY_GM_USER; } //anindagm i in
   978 | 
   979 | 	virtual bool isDead() { return m_bResHpType == USER_DEAD || m_sHp <= 0; }
   980 | 	virtual bool isBlinking() { return m_bAbnormalType == ABNORMAL_BLINKING; }
   981 | 	// SUSPENDED karakter "oyunda" sayılır: bölge listelerinde kalır ve mevcut
   982 | 	// kalıcılık/zamanlayıcı akışları bozulmaz; yalnızca paketleri filtrelenir.
   983 | 	INLINE bool isInGame() {
   984 | 		return GetState() == GameState::GAME_STATE_INGAME
   985 | 			|| GetState() == GameState::GAME_STATE_SUSPENDED;
   986 | 	}
   987 | 
   988 | 	// Reconnect sistemi: karakter askıya alınmış (işlevsiz) mı?
   989 | 	INLINE bool isSuspended() { return GetState() == GameState::GAME_STATE_SUSPENDED; }
   990 | 	INLINE CReconnectSuspend& GetReconnectSuspend() { return m_reconnectSuspend; }
   991 | 
   992 | 	INLINE bool isInAutoClan() { return GetClanID() == 1 || GetClanID() == 15001; }
   993 | 
   994 | 	INLINE bool isInParty() { return m_bInParty && m_bInEnterParty; }
   995 | 	INLINE bool isInSameParty(CUser* pTarget) { return m_sPartyIndex == pTarget->m_sPartyIndex && m_sPartyIndex != -1; }
   996 | 	INLINE bool isInApprovedParty() { return m_bInParty; }
   997 | 	INLINE bool isPartyLeader() { return isInParty() && m_bPartyLeader; }
   998 | 	INLINE bool isPartyCommandLeader() { return m_bPartyCommandLeader; }
   999 | 
  1000 | 	INLINE bool isInClan() { return GetClanID() > 0; }
  1001 | 	INLINE bool isKing() { return m_bRank == 1; }
  1002 | 	INLINE bool isClanLeader() { return GetFame() == CHIEF; }
  1003 | 	INLINE bool isClanAssistant() { return GetFame() == VICECHIEF; }
  1004 | 	INLINE bool isSlaveMerchant() { return m_bSlaveMerchant; }
  1005 | 	INLINE int16 GetSlaveGetID() { return m_bSlaveUserID; }
  1006 | 	INLINE bool isInValidRoom(uint8 type, uint16 roomid = 0) {
  1007 | 		/* 0: temple room
  1008 | 		1: stone room
  1009 | 		2: draki room */
  1010 | 		uint16 v_roomid = roomid > 0 ? roomid : GetEventRoom();
  1011 | 		if (type == 0)
  1012 | 			return isInTempleEventZone() && v_roomid > 0 && v_roomid <= MAX_TEMPLE_EVENT_ROOM;
  1013 | 		else if (type == 1)
  1014 | 			return isInMonsterStoneZone() && v_roomid > 0 && v_roomid <= MAX_MONSTER_STONE_ROOM;
  1015 | 		return false;

